package com.gr.aspect;

import com.auth0.jwt.interfaces.DecodedJWT;
import com.gr.util.JwtUtils;
import org.apache.commons.lang.StringUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import java.lang.reflect.Method;
import java.time.LocalDateTime;

@Component//让spring管理起来这个类
@Aspect//表示该类是一个增强类
public class LogAspect {
    private Logger logger= LoggerFactory.getLogger(LogAspect.class);
    //目标方法上面增加注解LogAnnotation的都是需要增加额外功能的目标方法
    @Pointcut("@annotation(com.gr.annotation.LogAnnotation)")
    public void pointcut(){}
    /**
     * 增加后置处理方法,后置增强日志记录方法
     * @param joinPoint 链接点，可以获取到目标对象的相关信息,日志记录浏览器调用方法信息
     */
    @After("pointcut()")//表示一个后置增强,绑定切入点
    public void logAfter(JoinPoint joinPoint){
        //signature可以获取到目标方法信息，比如方法名、参数
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();//获取到目标方法
        String name = method.getName();//拿到方法名
        Object[] args = joinPoint.getArgs();//目标方法参数列表,可能有多个参数
        //将数组转化为字符串方便查看
        String argsStr = StringUtils.join(args, "-");//参数
        LocalDateTime now = LocalDateTime.now();//时间
        //获取当前用户信息,用户信息在jwt里面，jwt又在request的header，所以我们需要获取request对象,java类不能直接拿request对象
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();//可以拿到request的Attributes
        String token = requestAttributes.getRequest().getHeader("authorization");
        String userid="";
        if (token!=null){
            //获取token里面的用户信息,要结束token工具
            DecodedJWT verify = JwtUtils.verify(token);
            userid = verify.getClaim("userid").asString();
        }
        //记录日志，记录谁在什么时间做了那个方法，传递的参数是什么
        //项目跑起来就没有控制台，这时候用日志工具来记录日志，指定日志级别
        logger.info("当前系统时间：{},当前用户是:{},进入到的方法是:{},携带的参数是:{}",now,userid,name,argsStr);
    }
}
